package com.hundun.vision.biz.robot;

import com.hundun.vision.biz.core.BollingerBandBuyStrategy;
import com.hundun.vision.biz.dto.PositionDTO;
import com.hundun.vision.biz.dto.SymbolDTO;
import com.hundun.vision.biz.enums.OrderSide;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.ta4j.core.*;
import org.ta4j.core.num.DecimalNum;

import java.math.BigDecimal;

import static com.hundun.vision.biz.enums.OrderSide.BUY;
import static com.hundun.vision.biz.enums.OrderSide.SELL;
import static java.math.RoundingMode.DOWN;

/**
 * @author ：RuoChen
 * @date ：10:10 2024/11/30
 * @description：做多机器人
 */
@Service
@Slf4j
public class BuyRobot extends Robot {
    public void check() {
        try {
            TradingRecord tradingRecord = null;
            accountService.changeLeverage(buySymbol, leverage);
            BarSeries barSeries = getBarSeries(buySymbol);
            if (barSeries == null) {
                return;
            }
            SymbolDTO symbolDTO = marketService.getSymbol(buySymbol);
            if (symbolDTO == null) {
                return;
            }
            Strategy buyStrategy = BollingerBandBuyStrategy.buildStrategy(barSeries, buyStopLossPercentage, buySymbol, symbolDTO.getPricePrecision());
            int endIndex = barSeries.getEndIndex();
            BigDecimal price = barSeries.getBar(endIndex).getClosePrice().bigDecimalValue();
            OrderSide orderSide = null;
            BigDecimal position = BigDecimal.ZERO;
            BigDecimal entryPrice = BigDecimal.ZERO;
            PositionDTO positionDTO = accountService.getPosition(buySymbol);
            if (positionDTO != null) {
                orderSide = getOrderSide(positionDTO);
                tradingRecord = initTradeRecord(positionDTO);
                position = positionDTO.getPositionAmt().abs();
                entryPrice = positionDTO.getEntryPrice();
                leverage = positionDTO.getLeverage();
            }
            if (buyStrategy.shouldEnter(endIndex, tradingRecord) && orderSide == null && !accountService.openOrder(buySymbol)) {
                BigDecimal balance = accountService.getBalance(BASE_COIN);
                BigDecimal amount = balance.multiply(balanceWeight).multiply(BigDecimal.valueOf(leverage)).divide(price, 0, DOWN);
                log.info("start create buy order,price:{}|amount:{}", price, amount);
                createOrder(buySymbol, true, BUY, false, price, amount);
                tradingRecord = new BaseTradingRecord(Trade.TradeType.BUY);
                tradingRecord.enter(1, DecimalNum.valueOf(price), DecimalNum.valueOf(amount));
            } else if (buyStrategy.shouldExit(endIndex, tradingRecord) && BUY.equals(orderSide)) {
                if (price.compareTo(entryPrice) > 0) {
                    log.info("buy take profit,price:{}|amount:{}", price, position);
                } else {
                    log.info("buy stop loss,price:{}|amount:{}", price, position);
                }
                createOrder(buySymbol, false, SELL, false, price, position);
                tradingRecord.exit(1, DecimalNum.valueOf(price), DecimalNum.valueOf(position));
            }
        } catch (Exception e) {
            log.error("Error occurred while loop: {}", e.getMessage());
        }
    }
}